package com.ycy.lucene.search;

import com.ycy.lucene.index.IndexReadDemo;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.NumericDocValuesField;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.junit.Test;

public class BasicQuery {

  /**
   * 普通查询
   */
  @Test
  public void search0() {
    try {
      String queryStr = "name:mc";
      Analyzer analyzer = new StandardAnalyzer();
      QueryParser queryParser = new QueryParser(null, analyzer);
      Query parse = queryParser.parse(queryStr);
      System.out.println(parse.toString());
      IndexReadDemo.search(parse, 2, Sort.RELEVANCE);//
    } catch (ParseException e) {
      e.printStackTrace();
    }
  }

  @Test
  public void search01() {
    try {
      /*
      1 经过分词之后 生成term
      2 通过term 查询
      3 文档中包含 部分 term 即可命中
      4 命中后 即可打分
       */
      String queryStr = "name:mc星巴克密室逃脱";
      Analyzer analyzer = new StandardAnalyzer();
      QueryParser queryParser = new QueryParser(null, analyzer);
      Query parse = queryParser.parse(queryStr);
      System.out.println(parse.toString());
      IndexReadDemo.search(parse, 2, Sort.RELEVANCE);//
    } catch (ParseException e) {
      e.printStackTrace();
    }
  }

  @Test
  public void search11() {
    try {
      TermQuery termQuery = new TermQuery(new Term("name", "星巴克"));
      IndexReadDemo.search(termQuery);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  @Test
  public void search111() {
    try {
      TermQuery termQuery = new TermQuery(new Term("id", "22130906"));
      IndexReadDemo.search(termQuery);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }


  /**
   * 段落查询
   * 20240530 查询需要两个要素, 顺序、完全匹配
   */
  @Test
  public void test(){
    PhraseQuery.Builder builder = new PhraseQuery.Builder();
    // 查询filed 声明的顺序,会影响结果吗?
    // 20240530 要求文档必须全部包含term,同时 文档中 term出现的顺序 要跟查询时声明的顺序一致
    // 20240615 为了理解 slop 可以把 查询的 term 颠倒一下。再调整一下slop 就能理解了。 slop 是指 文档中的包含的term 在指定的编辑距离之内 能满足查询term的顺序要求
    builder.add(new Term("name", "逃脱"));
    builder.add(new Term("name", "真人"));
    //默认情况下slop 为0, 所以不设置slop时,只能查到hello word
    builder.setSlop(3);
    PhraseQuery phraseQuery = builder.build();
    IndexReadDemo.search(phraseQuery, 10, Sort.RELEVANCE);
  }

  /**
   * 段落查询
   */
  @Test
  public void phraseQuery() {
    PhraseQuery phraseQuery1 = new PhraseQuery(10, "name", "脱", "密");
    IndexReadDemo.search(phraseQuery1, 10, null);
  }

  /**
   * 段落查询
   * 对于表达式中引号里面的文本，都会被分词，转化成一个PhraseQuery对象
   */
  @Test
  public void search1() {
    try {
      String queryStr = "name:\"MC 店\"~100";
      queryStr  ="name:\"long  read\""; //查询不出来，默认情况下slop=0,这就要求查询结果和查询词必须完全匹配
      queryStr  ="name:\"long time   read\""; //查询无结果
      queryStr  ="name:\"long time   read\"~5"; //查询成功
      queryStr  ="name:\"long time   read\"~1"; //查询成功
      Analyzer analyzer = new StandardAnalyzer();
      QueryParser queryParser = new QueryParser(null, analyzer);
      Query parse = queryParser.parse(queryStr);
      System.out.println(parse.toString());
      IndexReadDemo.search(parse);

    } catch (Exception e) {
      e.printStackTrace();
    }
  }




  /**
   * 通配符
   */
  @Test
  public void wildcardQuery() {
    try {
      /*
       *  hello*: 零个或者多个
       *  hello?: 一个
       */
      String queryStr = "name:Let*";
      QueryParser queryParser = new QueryParser(null, null);
      Query parse = queryParser.parse(queryStr);
      System.out.println(parse.toString());
      IndexReadDemo.search(parse, 2, null);

      WildcardQuery wildcardQuery = new WildcardQuery(new Term("name", "let*"));
      System.out.println(wildcardQuery.toString());
      IndexReadDemo.search(wildcardQuery, 10, null);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * 是 或 非 查询
   */
  public static void search3() {
    try {
/*    String queryStr = "+filename:hello +filename:word\"";
    Analyzer analyzer = new SimpleAnalyzer();
    QueryParser queryParser = new QueryParser(IndexCreateDemo.FIELD1, analyzer);
    Query parse = queryParser.parse(queryStr);*/

      BooleanQuery.Builder builder = new BooleanQuery.Builder();
      builder.add(new TermQuery(new Term("name", "白")), BooleanClause.Occur.MUST);
      builder.add(new TermQuery(new Term("name", "word")), BooleanClause.Occur.MUST_NOT);
      BooleanQuery build = builder.build();

      IndexReadDemo.search(build, 3, null);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * 范围查询
   */
  @Test
  public void rangQuery() {
    PhraseQuery termQuery = new PhraseQuery(20, "name", "密", "脱");
    IndexReadDemo.search(termQuery, 100, null);

    BooleanQuery.Builder builder = new BooleanQuery.Builder();
    //termrangQuery只适合文本
//    TermRangeQuery rangeQuery
//            = new TermRangeQuery("sales", new BytesRef(2), new BytesRef(5), true, true);
    Query rangeQuery
            = NumericDocValuesField.newSlowRangeQuery("sales", 2, 3);
    PhraseQuery termQuery1 = new PhraseQuery(20, "name", "密", "脱");
    builder.add(termQuery1, BooleanClause.Occur.MUST);
    builder.add(rangeQuery, BooleanClause.Occur.MUST);  //查询范围
    IndexReadDemo.search(builder.build(), 100, null);

  }

  /**
   * 自定义 querypharse
   */
  public static void search4() {

//    QueryParser queryParser  = new QueryParser(){
//      @Override
//      protected Query getFieldQuery(String field, String queryText, boolean quoted) throws ParseException {
//        return super.getFieldQuery(field, queryText, quoted);
//      }
//    };
//
  }


}
